// @flow

import React from 'react'
import moment from 'moment'
// import { LoginFetch } from 'store/modules/fetch'
import { connect } from 'react-redux'
import ReactDom from 'react-dom'
import styles from './DynamicLine.css'
import { message, Tabs, Modal, Tag } from 'antd'
// import Highcharts from 'highcharts-release'
import HighStock from 'highcharts-release/highstock.js'

import HighchartsCustomEvents from 'highcharts-custom-events'
import basicContext from 'basiccontext'
import 'basiccontext/dist/basicContext.min.css'
import 'basiccontext/dist/themes/bright.min.css'
import 'basiccontext/dist/addons/popin.min.css'
import HistoryPolar from 'components/HistoryPolar2'
import HistoryPolarAxis from 'components/HistoryPolarAxis2'
import Spectrum from 'components/Spectrum2'
import Bode from 'components/Bode'
import AddChartEvent from 'components/AddChartEvent'
import universalFetch, { handleFetchError, LoginFetch } from 'store/modules/fetch'
import { changeHistoryChartCond,
  changeDynamicChartCond, changeDynamicDateCond } from 'store/modules/deviceFileCondition'
const TabPane = Tabs.TabPane

HighchartsCustomEvents(HighStock)

type Props = {
  dynamicChartViewNow: boolean,
  dynamicIndicator: any,
  historyFrom: number,
  historyTo: number,
  chartData: Array<any>,
  title: String,
  yTitle: String,
  showContextMenu?: boolean,
  type?: string,
  deviceCard: Object,
  updateEvents: Function,
  deviceFileCondition: Object,
  userId: string
}
type State = {
  chart: Object,
  chartData: Array<Object>,
  spectrumVisible: boolean,
  visible: boolean,
  checkTime: any,
  checkName: string,
  activeKey: string,
  channel_id: number
}

let innerChart = {}

class DynamicLine extends React.Component {
  state: State
  props: Props
  interval: number
  websocketInit: Function
  drawChart: Function
  initialDraw: Function
  websocket: Object
  addEvents: Function
  showChart: Function
  closeModal: Function
  removeEventsModal: Function
  changeTab: Function
  constructor (props: Props) {
    super(props)
    this.state = {
      chart: {},
      chartData: [],
      spectrumVisible: false,
      visible: false,
      checkTime: '',
      checkName: '',
      activeKey: 'spectrum',
      channel_id: 0
    }
    this.websocketInit = this.websocketInit.bind(this)
    this.drawChart = this.drawChart.bind(this)
    this.initialDraw = this.initialDraw.bind(this)
    this.addEvents = this.addEvents.bind(this)
    this.showChart = this.showChart.bind(this)
    this.changeTab = this.changeTab.bind(this)
    this.closeModal = this.closeModal.bind(this)
    this.removeEventsModal = this.removeEventsModal.bind(this)
  }

  componentDidMount () {
    // dynamicChartViewNow可以在实现切换图类型后执行本组件的同时解决掉总览页跳工况页先加载上个测点的bug
    const { dynamicChartViewNow } = this.props
    if (dynamicChartViewNow) {
      clearInterval(this.interval)
      this.initialDraw(this.props)
    }
  }

  componentWillReceiveProps (nextProps) {
    // 不用判断是否相同，否则只改变channelId时不会执行
    clearInterval(this.interval)
    this.initialDraw(nextProps)
  }

  componentWillUnmount () {
    clearInterval(this.interval)
  }

  addEvents (e: Object) {
    const { x, series } = e.point
    const { deviceCard, updateEvents, userId } = this.props
    const container = this.refs.chartEvent
    universalFetch(`${__SERVICE_API__}sys/users/${userId}`)
      .then(res => res.json())
      .then((json) => {
        const userName = json.result.name
        ReactDom.render(
          <AddChartEvent {...{
            userName,
            eventTime: x,
            deviceCard,
            updateEvents,
            removeEventsModal: this.removeEventsModal,
            channel_id: series.options.compoundId.channel_id,
            variableNameEn: series.options.field,
            sensorNameEn: series.options.sensorNameEn,
            sensorName: series.options.sensorName,
            checkName: series.name
          }} />,
          container
        )
      })
      .catch((error) => {
        handleFetchError(error)
        console.error(error)
      })
  }

  removeEventsModal () {
    const container = this.refs.chartEvent
    ReactDom.unmountComponentAtNode(container)
  }
  closeModal () {
    this.setState({
      visible: false
    })
  }
  showChart (e: Object, active) {
    const { x, series } = e.point
    // series.name.split('__')[1]
    this.setState({
      visible: true,
      checkTime: x,
      channel_id: series.options.compoundId.channel_id,
      checkName: series.name, // '通频值__YT111A'
      activeKey: active
    })
  }
  changeTab (key: string) {
    this.setState({
      activeKey: key
    })
  }

  websocketInit (series) { // 前端需要自动刷新，几秒请求一次接口
    const { dynamicCond } = this.props.deviceFileCondition
    // const { monitors, keyNameValue } = dynamicCond
    const { monitors } = dynamicCond
    const { deviceData } = this.props.deviceCard
    const deviceNo = deviceData.deviceNo.split('_')
    const res = monitors.map((monitorsItem, i) => {
      // channelNames = monitorsItem.channelNames
      // const nowTime = moment()
      // let postBody = {
      //   fieldGroup: monitorsItem.En,
      //   fields: monitorsItem.key,
      //   coValueFilter: {
      //     idFieldFilter: {
      //       factory_id: { '$eq': String(deviceNo[0]) },
      //       equipment_id: { '$eq': String(deviceNo[1]) },
      //       machine_id: { '$eq': String(deviceNo[2]) },
      //       datatype: { '$eq': '1' },
      //       '$or': monitorsItem.channelIds.map((d, i) => {
      //         return { 'channel_id': { '$eq': String(d) } }
      //       })
      //     }
      //   },
      //   timeRange: {
      //     // start: moment().subtract(30, 'm').format('YYYY-MM-DDTHH:mm:ss.SSSZ'),
      //     // end: moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ')
      //     start:'now-30m',
      //     end: 'now'
      //   },
      //   order: [{ '$default': 'asc' }],
      //   size: 30,
      //   page: 1
      // }
      let url = `${__KMX_TSDB_QUERY_URL__}kmx/tsdb/query?type=data-streams`
      const token = localStorage.getItem('asset_token')
      let header = {
        'Content-Type': 'application/json',
        'X-Auth':token
      }
      let postBody = {
        'tsTable' : monitorsItem.En,
        // 'allCol' : 'true',
        'startTime' : moment().subtract(30, 'm').unix(),
        // 'endTime' : moment().unix(),
        'queryConditions' : [
          {
            'colName' : 'factory_id',
            'condition' : 'eq',
            'value' : String(deviceNo[0])
          },
          {
            'colName' : 'equipment_id',
            'condition' : 'eq',
            'value' : String(deviceNo[1])
          },
          {
            'colName' : 'machine_id',
            'condition' : 'eq',
            'value' : String(deviceNo[2])
          },
          {
            'colName' : 'datatype',
            'condition' : 'eq',
            'value' : 1
          },
          {
            'colName' : 'channel_id',
            'condition' : 'in',
            'value' : monitorsItem.channelIds
          }
        ],
        cols : monitorsItem.key
      }
      if (monitorsItem.En === 'c_sta') { // 如果是过程量就请求channel_type = 1 的值
        header = {
          'Content-Type': 'application/json'
        }
        postBody = {
          fieldGroup: monitorsItem.En,
          fields: monitorsItem.key,
          coValueFilter: {
            idFieldFilter: {
              factory_id: { '$eq': String(deviceNo[0]) },
              equipment_id: { '$eq': String(deviceNo[1]) },
              machine_id: { '$eq': String(deviceNo[2]) },
              datatype: { '$eq': '1' },
              '$or': monitorsItem.channelIds.map((d, i) => {
                return { 'channel_id': { '$eq': String(d) } }
              })
            }
          },
          timeRange: {
            // start: moment().subtract(30, 'm').format('YYYY-MM-DDTHH:mm:ss.SSSZ'),
            // end: moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ')
            start:'now-30m',
            end: 'now'
          },
          order: [{ '$default': 'asc' }],
          size: 30,
          page: 1
        }
        postBody.coValueFilter.idFieldFilter['channel_type'] = { '$eq': '1' }
        url = `${__KMX_API__}data-streams`
      }
      if (monitorsItem.En === 'c_vib') {
        header = {
          'Content-Type': 'application/json'
        }
        postBody = {
          fieldGroup: monitorsItem.En,
          fields: monitorsItem.key,
          coValueFilter: {
            idFieldFilter: {
              factory_id: { '$eq': String(deviceNo[0]) },
              equipment_id: { '$eq': String(deviceNo[1]) },
              machine_id: { '$eq': String(deviceNo[2]) },
              datatype: { '$eq': '1' },
              '$or': monitorsItem.channelIds.map((d, i) => {
                return { 'channel_id': { '$eq': String(d) } }
              })
            }
          },
          timeRange: {
            // start: moment().subtract(30, 'm').format('YYYY-MM-DDTHH:mm:ss.SSSZ'),
            // end: moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ')
            start:'now-30m',
            end: 'now'
          },
          order: [{ '$default': 'asc' }],
          size: 30,
          page: 1
        }
        url = `${__KMX_API__}data-streams`
      }
      return LoginFetch(url, {
      // return LoginFetch(`${__KMX_API__}data-streams`, {
        method: 'POST',
        headers: header,
        body: JSON.stringify(postBody)
      }).then((res) => res.json())
    })
    Promise.all(res).then((jsons) => {
      let results = []
      jsons.map((d) => {
        if (d.result !== undefined) {
          results.push(...d.result)
        } else {
          results.push(...d.results)
        }
      })
      if (results && results.length > 0) {
        // const x = (new Date()).getTime()
        // const y = [Math.random(), Math.random(), Math.random()]
        // series.map((d, i) => {
        //   if (d) {
        //     d.addPoint([x, y[i]], true, true)
        //   }
        // })
        series.map((d, i) => {
          if (d && results[i]) {
            if (results[i].streams.length > 0 || results[i].stream.length > 0) {
              const streams = results[i]['streams'] || results[i]['stream']
              // 过滤掉tcs中小于-1000000的值
              if (streams[0][1] > -1000000) {
                d.addPoint(streams[0], true, true)
              }
            }
          }
        })
      }
    })
    .catch(() => {})
  }

  queryHistoryData (monitors, keyNameValue, start, end) { // 工况实时数据单图显示
    const { deviceData } = this.props.deviceCard
    const deviceNo = deviceData.deviceNo.split('_')
    let channelNames = []
    const res = monitors.map((monitorsItem, i) => {
      channelNames = monitorsItem.channelNames
      // const nowTime = moment()
      // let postBody = {
      //   fieldGroup: monitorsItem.En,
      //   fields: monitorsItem.key,
      //   coValueFilter: {
      //     idFieldFilter: {
      //       factory_id: { '$eq': String(deviceNo[0]) },
      //       equipment_id: { '$eq': String(deviceNo[1]) },
      //       machine_id: { '$eq': String(deviceNo[2]) },
      //       datatype: { '$eq': '1' },
      //       '$or': monitorsItem.channelIds.map((d, i) => {
      //         return { 'channel_id': { '$eq': String(d) } }
      //       })
      //     }
      //   },
      //   timeRange: {
      //     // start: moment().subtract(30, 'm').format('YYYY-MM-DDTHH:mm:ss.SSSZ'),
      //     // end: moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ')
      //     start:'now-30m',
      //     end: 'now'
      //   },
      //   order: [{ '$default': 'asc' }],
      //   size: 30,
      //   page: 1
      // }
      let url = `${__KMX_TSDB_QUERY_URL__}kmx/tsdb/query?type=data-streams`
      const token = localStorage.getItem('asset_token')
      let header = {
        'Content-Type': 'application/json',
        'X-Auth':token
      }
      let postBody = {
        'tsTable' : monitorsItem.En,
        // 'allCol' : 'true',
        'startTime' : moment().subtract(30, 'm').unix(),
        // 'endTime' : moment().unix(),
        'queryConditions' : [
          {
            'colName' : 'factory_id',
            'condition' : 'eq',
            'value' : String(deviceNo[0])
          },
          {
            'colName' : 'equipment_id',
            'condition' : 'eq',
            'value' : String(deviceNo[1])
          },
          {
            'colName' : 'machine_id',
            'condition' : 'eq',
            'value' : String(deviceNo[2])
          },
          {
            'colName' : 'datatype',
            'condition' : 'eq',
            'value' : 1
          },
          {
            'colName' : 'channel_id',
            'condition' : 'in',
            'value' : monitorsItem.channelIds
          }
        ],
        cols : monitorsItem.key
      }
      if (monitorsItem.En === 'c_sta') { // 如果是过程量就请求channel_type = 1 的值
        header = {
          'Content-Type': 'application/json'
        }
        postBody = {
          fieldGroup: monitorsItem.En,
          fields: monitorsItem.key,
          coValueFilter: {
            idFieldFilter: {
              factory_id: { '$eq': String(deviceNo[0]) },
              equipment_id: { '$eq': String(deviceNo[1]) },
              machine_id: { '$eq': String(deviceNo[2]) },
              datatype: { '$eq': '1' },
              '$or': monitorsItem.channelIds.map((d, i) => {
                return { 'channel_id': { '$eq': String(d) } }
              })
            }
          },
          timeRange: {
            // start: moment().subtract(30, 'm').format('YYYY-MM-DDTHH:mm:ss.SSSZ'),
            // end: moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ')
            start:'now-30m',
            end: 'now'
          },
          order: [{ '$default': 'asc' }],
          size: 30,
          page: 1
        }
        postBody.coValueFilter.idFieldFilter['channel_type'] = { '$eq': '1' }
        url = `${__KMX_API__}data-streams`
      }
      if (monitorsItem.En === 'c_vib') {
        header = {
          'Content-Type': 'application/json'
        }
        postBody = {
          fieldGroup: monitorsItem.En,
          fields: monitorsItem.key,
          coValueFilter: {
            idFieldFilter: {
              factory_id: { '$eq': String(deviceNo[0]) },
              equipment_id: { '$eq': String(deviceNo[1]) },
              machine_id: { '$eq': String(deviceNo[2]) },
              datatype: { '$eq': '1' },
              '$or': monitorsItem.channelIds.map((d, i) => {
                return { 'channel_id': { '$eq': String(d) } }
              })
            }
          },
          timeRange: {
            // start: moment().subtract(30, 'm').format('YYYY-MM-DDTHH:mm:ss.SSSZ'),
            // end: moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ')
            start:'now-30m',
            end: 'now'
          },
          order: [{ '$default': 'asc' }],
          size: 30,
          page: 1
        }
        url = `${__KMX_API__}data-streams`
      }
      return LoginFetch(url, {
      // return LoginFetch(`${__KMX_API__}data-streams`, {
        method: 'POST',
        headers: header,
        body: JSON.stringify(postBody)
      }).then((res) => res.json())
    })
    Promise.all(res).then((jsons) => {
      let results = []
      jsons.map((d) => {
        if (d.code === 1) {
          message.error('请求数据失败: ' + d.message, 10)
          this.setState({
            chartData: []
          }, () => {
            this.drawChart()
          })
          return
        }
        if (d.result !== undefined) {
          results.push(...d.result)
        } else {
          results.push(...d.results)
        }
      })
      let monitorNames = []
      monitors.map((d) => {
        monitorNames.push(...d.keyName)
      })
      if (results && results.length > 0) {
        this.setState({
          chartData: results.map((data, index) => {
            const channelArray = channelNames.filter((dd) => dd.id === data.compoundId.channel_id)
            const name = monitorNames.filter((dd) => dd.key === data.field || data.field)[0].name
            const monitIndex = monitors.filter((dd) => dd.key[0] || dd.key.indexOf(data.field || data.field) > -1)
            data['name'] = name + '__' + channelArray[0].name
            data['type'] = 'line'
            let stream = []
            // 过滤掉tcs中小于-1000000的值
            if (data.stream !== undefined) {
              data.stream.map((d, i) => {
                if (d[1] > -1000000) {
                  stream.push(d)
                }
              })
            } else {
              data.streams.map((d, i) => {
                if (d[1] > -1000000) {
                  stream.push(d)
                }
              })
            }
            data['data'] = stream
            const len = data['data'].length
            if (len < 30) {
              let Time = moment().format('X')
              for (let i = 0; i < (30 - len); i++) {
                data['data'].unshift({ time:(Number(Time) - i) * 1000, value: 0 })
              }
            }
            data['sensorNameEn'] = monitIndex[0].En // 用于底部事件名称点击绘图
            data['sensorName'] = monitIndex[0].sensorType // 用于底部事件名称点击绘图
            return data
          })
        }, () => {
          this.drawChart()
        })
      }
    })
    // .catch((error) => {
    //   console.log(error);
    //   message.error('请求数据失败: ' + error.message, 10)
    //   this.setState({
    //     chartData: []
    //   }, () => {
    //     this.drawChart()
    //   })
    // })
  }

  drawChart () {
    const that = this
    const container = this.refs.container
    let component = this
    // y轴的最小值（如果都是正数，最小值为0，有负数就不设置最小值）
    let minValue = 0
    this.state.chartData.map((d, i) => {
      if (d.stream !== undefined) {
        d.stream.map((dd, ii) => {
          if (dd['value'] < 0 || dd[1] < 0) {
            minValue = null
          }
        })
      } else {
        d.streams.map((dd, ii) => {
          if (dd['value'] < 0 || dd[1] < 0) {
            minValue = null
          }
        })
      }
    })
    HighStock.setOptions({ global: { useUTC: false } })
    innerChart = HighStock.StockChart(container, {
      chart: {
        type: 'line',
        zoomType: 'x',
        animation: HighStock.svg,
        events: {
          load: function () {
            const series = this.series
            clearInterval(component.interval)
            component.interval = setInterval(function () {
              component.websocketInit(series)
            }, 5000)
          }
        }
      },
      title: {
        text: ''
      },
      rangeSelector : {
        enabled: false,
        buttons : [{
          type : 'all',
          count : 1,
          text : 'All'
        }],
        selected : 1,
        inputEnabled : false
      },
      credits:{
        enabled: false
      },
      xAxis: {
        type: 'datetime',
        dateTimeLabelFormats: {
          second: '%Y-%m-%d<br>%H:%M:%S',
          minute: '%Y-%m-%d<br>%H:%M',
          hour: '%Y-%m-%d<br>%H:%M',
          day: '%Y-%m-%d',
          week: '%Y-%m-%d',
          month: '%Y-%m',
          year: '%Y'
        }
        // categories: this.state.categories
      },
      yAxis: {
        opposite: false,
        lineWidth: 1,
        min: minValue,
        title: {
          align: 'high',
          offset: 0,
          rotation: 0,
          y: -10,
          text: ''
        },
        plotLines: [{
          value: 0,
          width: 1,
          color: '#808080'
        }]
      },
      navigator: {
        height: 30,
        yAxis: {
          min: minValue
        }
      },
      tooltip: {
        shared: true,
        useHTML: true,
        formatter: function () {
          let t = '<b>' + moment(this.x, 'x').format('YYYY-MM-DD HH:mm:ss') + '</b>' +
            '<table>'
          this.points.map(function (d, i) {
            const y = d.y.toFixed(3) * 1000 / 1000
            t += '<tr><td style="color: ' + d.series.color + '">' + d.series.name + ': </td>' +
              '<td style="text-align: right"><b>' + y + '</b></td></tr>'
          })
          t += '</table>'
          return t
        }
        // valueDecimals: 2
      },
      legend: {
        enabled: true,
        verticalAlign: 'top'
      },
      exporting: {
        enabled: false
      },
      // plotOptions: {
      //   series: {
      //     animation: true,
      //     cursor: 'pointer'
      //     // marker: {
      //     //   enabled: false
      //     // }
      //   }
      // },
      plotOptions: {
        line: {
          lineWidth: 1,
          dataGrouping: {
            enabled: false
          }
        },
        series: {
          animation: true,
          cursor: 'pointer',
          point: {
            events: {
              contextmenu: (e) => {
                if (!this.props.showContextMenu && this.state.chartData[0].sensorNameEn.indexOf('tcs') === -1) {
                  const contextMenu = [
                    {
                      title: '添加事件',
                      icon: 'fa fa-plus',
                      fn: () => {
                        that.addEvents(e)
                      }
                    },
                    {
                      title: '波形频谱图',
                      icon: 'fa fa-line-chart',
                      fn: () => {
                        that.showChart(e, 'spectrum')
                      }
                    },
                    {
                      title: '原始轴心轨迹图',
                      icon: 'fa fa-eercast',
                      fn: () => {
                        that.showChart(e, 'polarAxis')
                      }
                    },
                    {
                      title: '合成轴心轨迹图',
                      icon: 'fa fa-bullseye',
                      fn: () => {
                        that.showChart(e, 'polar')
                      }
                    },
                    {
                      title: '伯德图',
                      icon: 'fa fa-area-chart',
                      fn: () => {
                        that.showChart(e, 'bode')
                      }
                    }
                  ]

                  basicContext.show(contextMenu, e)
                }
              }
            }
          }
        }
      },
      series: this.state.chartData
    })
    setTimeout(() => {
      innerChart.reflow()
    }, 5)
  }

  initialDraw (props) {
    const { dynamicCond, dynamicDate } = props.deviceFileCondition
    const { monitors, keyNameValue } = dynamicCond
    const { startTime, endTime } = dynamicDate
    if (!monitors) {
      // message.info('暂无数据')
      // this.drawChart()
      return
    }
    this.queryHistoryData(
      monitors,
      keyNameValue,
      startTime.format('YYYY-MM-DDTHH:mm:ss.SSSZ'),
      endTime.format('YYYY-MM-DDTHH:mm:ss.SSSZ')
    )
  }

  render () {
    const { visible, checkTime, activeKey, checkName, channel_id } = this.state
    const { type, deviceCard, deviceFileCondition } = this.props
    const title = deviceCard.deviceData.customerName + '/' + deviceCard.deviceData.name
    const operations = <Tag style={{ marginRight: 20, cursor: 'default' }}>设备：{title}</Tag>
    return (
      <div>
        <div ref='container' className={styles['container']} />
        <div ref='chartEvent' />
        <Modal
          width={1000}
          style={{ top: '5%' }}
          maskClosable={false}
          visible={visible}
          onCancel={this.closeModal}
          footer={null}
          header={null}
          >
          <div>
            <Tabs tabBarExtraContent={operations} activeKey={activeKey} size='small' onChange={this.changeTab}>
              <TabPane tab='波形频谱图' key='spectrum'>
                <Spectrum {...{
                  type,
                  historyCond: deviceFileCondition.dynamicCond,
                  deviceData: deviceCard.deviceData,
                  checkTime,
                  checkName,
                  channel_id
                }} />
              </TabPane>
              <TabPane tab='原始轴心轨迹图' key='polarAxis'>
                <HistoryPolarAxis {...{
                  historyCond: deviceFileCondition.dynamicCond,
                  deviceData: deviceCard.deviceData,
                  channel_id,
                  checkTime
                }} />
              </TabPane>
              <TabPane tab='合成轴心轨迹图' key='polar'>
                <HistoryPolar {...{
                  historyCond: deviceFileCondition.dynamicCond,
                  deviceData: deviceCard.deviceData,
                  channel_id,
                  checkTime
                }} />
              </TabPane>
              <TabPane tab='伯德图' key='bode'>
                <Bode {...{
                  historyCond: deviceFileCondition.dynamicCond,
                  deviceData: deviceCard.deviceData,
                  channel_id
                }} />
              </TabPane>
            </Tabs>
          </div>
        </Modal>
      </div>
    )
  }
}

const mapStatesToProps = (state) => {
  return {
    deviceCard: state.deviceCard,
    deviceFileCondition: state.deviceFileCondition,
    userId: state.user.userId
  }
}
export default connect(mapStatesToProps, {
  changeHistoryChartCond, changeDynamicChartCond, changeDynamicDateCond })(DynamicLine)
